package com.twu.biblioteca;

import java.util.*;

import static com.twu.biblioteca.Movie.Rate.EIGHT;
import static com.twu.biblioteca.Movie.Rate.NINE;
import static com.twu.biblioteca.Movie.Rate.SEVEN;

/**
 * Created by fish on 14-7-16.
 */
public class Library {
    private ArrayList<Book> bookList;
    private ReservationManager reservationManager;
    private ArrayList<Movie> movieList;
    private UserManager userManager;

    public Library() {
        initialize();
    }

    private void initialize() {
        reservationManager = new ReservationManager();
        userManager = new UserManager();
        bookList = new ArrayList<>();
        bookList.addAll(Arrays.asList(
                new Book(1, "AA", 2001, "ADBB"),
                new Book(2, "DD", 2008, "C++"),
                new Book(4, "CC", 1976, "JAVA"),
                new Book(3, "BB", 2011, "FIFA")
        ));
        movieList = new ArrayList<>();
        movieList.addAll(Arrays.asList(
                new Movie("2012", 2011, "Director Who", EIGHT),
                new Movie("Titanic", 1987, "Director Famous", NINE),
                new Movie("Avatar", 2012, "James Cameron", NINE),
                new Movie("Snowpiercer", 2014, "奉俊昊", SEVEN)
        ));
        HashSet<User> users = new HashSet<User>();
        users.addAll(Arrays.asList(
                new User("Zhang San", "123456", "111-12345"),
                new User("Li Si", "123456", "123-12345"),
                new User("Wang Wu", "123456", "123-54321")
        ));
        userManager.setUsers(users);
    }

    public void setBookList(ArrayList<Book> bookList) {
        this.bookList = bookList;
    }

    public ArrayList<Book> getBookList() {
        return bookList;
    }

    public ReservationManager getReservationManger() {
        return reservationManager;
    }

    public boolean isBookAvailable(String bookTitle) {
        Book book = getBookByTitle(bookTitle);
        if(book==null) return false; // books does not exists
        return !reservationManager.getReservedBooks().containsKey(book); //book exists and if checked_out
    }

    public boolean isBookExist(String s) {
        return getBookByTitle(s) != null;
    }

    public void setMovieList(ArrayList<Movie> movieList) {
        this.movieList = movieList;
    }

    public ArrayList<Movie> getMovieList() {
        return movieList;
    }

    public Book getBookByTitle(String title) {
        Book searchedBook = null;
        for(Book book : getBookList()) {
            if(book.getTitle().equals(title)) {
                searchedBook = book;
            }
        }
        return searchedBook;
    }

    public Movie getMovieByName(String name) {
        Movie movie = null;
        for (Movie m : movieList) {
            if(m.getName().equals(name))
                movie = m;
        }
        return movie;
    }

    public boolean isMovieExist(String name) {
        return getMovieByName(name) != null;
    }

    public boolean isMovieAvailable(String name) {
        if(!isMovieExist(name)) return false;
        return !reservationManager.getReservedMovies().containsKey(getMovieByName(name));
    }

    public UserManager getUserManager() {
        return userManager;
    }

    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }

    class ReservationManager {
        public HashMap<Movie, User> getReservedMovies() {
            return reservedMovies;
        }

        private HashMap<Book,User> reservedBooks;
        private HashMap<Movie, User> reservedMovies;

        ReservationManager() {
            this.reservedBooks = new HashMap<>();
            this.reservedMovies = new HashMap<>();
        }

        public void addReservation(Book book, User user) {
            reservedBooks.put(book, user);
        }

        public HashMap<Book, User> getReservedBooks() {
            return reservedBooks;
        }

        public void addReservation(Movie movie, User user) {
            reservedMovies.put(movie, user);
        }

        public User getUserReserved(String title, String type) {
            if(type.toLowerCase().equals("book"))
            for (Book book : reservedBooks.keySet()) {
                if(book.getTitle().equals(title)) {
                    return reservedBooks.get(book);
                }
            }
            if(type.toLowerCase().equals("movie"))
            for (Movie movie : reservedMovies.keySet()) {
                if(movie.getName().equals(title)) {
                    return reservedMovies.get(movie);
                }
            }
            return null;
        }
    }

    class UserManager {
        private Set<User> users = new HashSet<>();
        private User currentUser = null;

        public void setUsers(Set<User> users) {
            this.users = users;
        }

        public void setCurrentUser(User currentUser) {
            this.currentUser = currentUser;
        }

        public Set<User> getUsers() {
            return users;
        }

        public User getCurrentUser() {
            return currentUser;
        }

        public boolean authenticate(final String libNum, String passwd) {
            for (User user : users) {
                if(user.getLibNumber().equals(libNum) &&
                        user.getPassword().equals(passwd)){
                    setCurrentUser(user);
                    return true;
                }
            }
            return false;
        }

        public User getUserByLibnum(String libNum) {
            User result = null;
            for (User user : users) {
                if(user.getLibNumber().equals(libNum))
                    result = user;
            }
            return result;
        }
    }
}
